package com.dynamic.mybatis.web.mvc;

import com.dynamic.mybatis.core.metadata.DynamicMappedStatement;
import com.dynamic.mybatis.core.session.DynamicSqlSessionTemplate;
import com.dynamic.mybatis.core.session.helper.DynamicMappedStatementHelper;
import com.dynamic.mybatis.core.utils.BeanUtils;
import com.dynamic.mybatis.core.utils.StringUtils;
import com.dynamic.mybatis.web.security.AuthenticationException;
import com.dynamic.mybatis.web.security.SecurityAuthorizationParameter;
import com.dynamic.mybatis.web.security.SecurityParameterHandler;
import com.dynamic.mybatis.web.security.SecurityParameterInterceptHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
public class MappedStatementRequestExecuteHandler {

    @Autowired
    private DynamicSqlSessionTemplate sqlSessionTemplate;

    @Autowired
    private SecurityParameterHandler securityParameterHandler;

    public Object execute(@RequestHeader HttpHeaders httpHeaders, @RequestAttribute("org.springframework.web.servlet.HandlerMapping.lookupPath") String url, @RequestParam Map<String, Object> urlParameter, @RequestBody(required = false) Object bodyParameter) {
        String contentType = httpHeaders.getFirst(HttpHeaders.CONTENT_TYPE);
        Object parameter = bodyParameter != null && StringUtils.isNotBlank(contentType) && contentType.contains(MediaType.APPLICATION_JSON_VALUE) ? BeanUtils.copy(bodyParameter, urlParameter) : urlParameter;

        String mappedStatementId = url.replaceAll("^/", "").replaceAll("/", ".");
        //token 处理
        Object param = tokenHandle(httpHeaders, parameter);
        //认证
        Object session = authenticateHandle(mappedStatementId, param);
        if (parameter instanceof Map && session != null) {
            ((Map) (parameter)).put("session", session);
        }
        //session处理
        //执行
        Object result = sqlSessionTemplate.execute(mappedStatementId, parameter);
        //登录处理
        result = loginHandle(mappedStatementId, parameter, result);
        return result;
    }


    private Object tokenHandle(HttpHeaders httpHeaders, Object parameter) {
        String token = httpHeaders.getFirst(HttpHeaders.AUTHORIZATION);
        Object param;
        if (!StringUtils.isNotEmpty(token)) {
            param = parameter;
        } else {
            param = new SecurityAuthorizationParameter(token, parameter);
        }
        return param;
    }


    private Object authenticateHandle(String mappedStatementId, Object param) {
        DynamicMappedStatement dms = sqlSessionTemplate.getDynamicMappedStatementHelper().getDynamicMappedStatement(mappedStatementId);
        if (dms == null) {
            return null;
        }
        if (dms.isSessionContext() || !dms.isAuth()) {
            if ((param instanceof SecurityAuthorizationParameter)) {
                SecurityAuthorizationParameter parameter = (SecurityAuthorizationParameter) param;
                return securityParameterHandler.getSecurityParameter(dms.getNamespace(), parameter.getToken());
            }
            return null;
        } else {
            //权限不足
            if (!(param instanceof SecurityAuthorizationParameter)) {
                throw new AuthenticationException("权限不足");
            }
            //权限不足
            SecurityAuthorizationParameter parameter = (SecurityAuthorizationParameter) param;
            if (StringUtils.isBlank(parameter.getToken())) {
                throw new AuthenticationException("权限不足");
            }
            Object session;
            try {
                session = securityParameterHandler.getSecurityParameter(dms.getNamespace(), parameter.getToken());
            } catch (Exception e) {
                throw new AuthenticationException("非法token");
            }
            if (session == null) {
                throw new AuthenticationException("token失效");
            }
            return session;
        }
    }

    /**
     * 　* @Description: 该接口为登录接口，使用登录接口的结果调用session类型的接口，并生成token,绑定用户和session并缓存
     *
     */
    private Object loginHandle(String mappedStatementId, Object parameter, Object result) {
        DynamicMappedStatementHelper dmsHelper = sqlSessionTemplate.getDynamicMappedStatementHelper();
        DynamicMappedStatement dms = sqlSessionTemplate.getDynamicMappedStatementHelper().getDynamicMappedStatement(mappedStatementId);
        if (dms == null) {
            return result;
        }
        if (dms.isSessionContext()) {
            DynamicMappedStatement dmsSession = dmsHelper.mappedStatementValues().stream().filter(DynamicMappedStatement::isSessionContext).findFirst().orElse(null);
            if (dmsSession != null && dmsSession.isEnable()) {
                Object sessionContext = sqlSessionTemplate.execute(mappedStatementId, parameter);
                String token = SecurityParameterInterceptHandler.generateToken(BeanUtils.copyGetMap(parameter));
                securityParameterHandler.setSecurityParameter(dmsSession.getNamespace(), token, sessionContext);
                result = token;
            }
        }
        return result;
    }

}
